#include <memory>
#include "TcpServer.hpp"
using namespace tcp_server;
static void Usage(std::string proc)
{
    std::cerr << "Usage:\n\t" << proc << "port" << "\n\n";
}
//根据传入的req，输出resp
bool Cal(const Request& req,Response& resp)
{
    resp._exitCode = OK;
    resp._result = OK;
    switch(req._op)
    {
    case '+':
        resp._result=req._x+req._y;
        break;
    case '-':
        resp._result=req._x-req._y;
        break;
    case '*':
        resp._result=req._x*req._y;
        break;
    case '/':
    {
        if(0==req._y){resp._exitCode=DIV_ZERO_ERR;}
        else
            resp._result=req._x/req._y;
    } 
        break;
    case '%':
    {
        if(0==req._y){resp._exitCode=MOD_ZERO_ERR;}
        else
        resp._result=req._x%req._y;
    }
        break;
    default:
        resp._exitCode=OP_ZERO_ERR;
        return false;
    }
    return true;
}
void calculate(Connection* conn)//读就绪后，会进行回调，进行计算的处理
{
    std::string onePackage;
    while(ParseOncePackage(conn->_inBuffer, &onePackage))
    {
        std::string reqStr;//从一个报文中解析出来的正文部分
        if(!deLength(onePackage, &reqStr)) { return; }//提取报文中的有效载荷
            std::cout << "仅剩有效载荷的请求：\n" << reqStr << std::endl;
        //二、对有效载荷进行反序列化。（将正文的string对象解析x,y,op存储至req对象中）
        Request req;//运算数与运算符对象
        if(!req.deserialize(reqStr)) { return; }
        Response resp;
        Cal(req, resp);
        //四、对得到的Response计算结果对象，进行序列化，得到一个"字符串"，发送给客户端
        std::string respStr;//输出型参数，获取序列化string类型的内容(resp_str是序列化后的字符串)
        resp.serialize(&respStr);//对计算结果对象resp进行序列化
        //五、先构建一个完整的报文，再将其添加到发送缓冲区中
        conn->_outBuffer = enLength(respStr);//对序列化数据添加自定义协议规则
        std::cout << "result" << conn->_outBuffer << std::endl;
    }
    //处理完了，直接发回去
    if (conn->_sender)
    {
        conn->_sender(conn);
    }
    //如果没有发送完毕，需要对对应的socket开启对写事件的关心，如果发完了，则关闭对写事件的关心
    // if (!conn->_outBuffer.empty())//如果没发完
    // {
    //     conn->_pTS->EnableReadWrite(conn, true, true);
    // }
    // else//如果发完了
    // {
    //     conn->_pTS->EnableReadWrite(conn, true, false);
    // }
}
int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);
    std::unique_ptr<TcpServer> tsvr(new TcpServer(calculate, port));
    tsvr->InitServer();
    tsvr->Dispatch();
    return 0;
}